#!/usr/bin/env python
#coding=utf8

import os
import time
from functools import reduce
import tornado
import tornado.web
from peewee import DQ,R

from core import util
from core import models

class Route(object):
    _routes = {}
    def __init__(self, pattern, kwargs={}, name=None, host='.*$'):
        self.pattern = pattern
        self.kwargs = {}
        self.name = name
        self.host = host
    def __call__(self, handler_class):
        spec = tornado.web.url(self.pattern, handler_class, self.kwargs, name=self.name)
        self._routes.setdefault(self.host, []).append(spec)
        return handler_class
    @classmethod
    def routes(cls, application=None):
        if application:
            for host, handlers in cls._routes.items():
                application.add_handlers(host, handlers)
        else:
            return reduce(lambda x,y:x+y, cls._routes.values()) if cls._routes else []

class BaseHandler(tornado.web.RequestHandler):
    pass

##############################################################################################
@Route(r'/admin/users', name='admin_user')
class UserHandler(BaseHandler):
    def get(self):
        page = int(self.get_argument("page", 1))
        pagesize = 10
        keyword = self.get_argument("keyword", None)
        ft = (User.id > 0)
        if keyword:
            keyword = keyword + '%'
            ft = ft & (User.umobile % keyword)
        uq = User.select().where(ft)
        total = uq.count()
        users = uq.paginate(page, pagesize).order_by(User.lastlogin.desc())
        self.render('admin/user.html', users = users, total = total, page = page, pagesize = pagesize)

@Route(r'/login', name='admin_login')
class LoginHandler(BaseHandler):
    def get(self):
        come_url = self.get_argument('next', '/')
        self.render('login.html',next=come_url)

    def post(self):
        umobile = self.get_argument('username', '')
        upwd = self.get_argument('password', '')
        if umobile and upwd:
           user = User.get(umobile = umobile)
           if user.check_password(upwd):
              self.set_secure_cookie('uid', str(user.id))
              user.update_login()
              return self.redirect(self.get_argument('next', '/'))
        return self.write("<script>alert('您输入的用户名或密码错误');history.back();</script>")

@Route(r'/logout', name='admin_logiout')
class LogoutHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.clear_cookie('uid')
        self.redirect(self.get_argument("next", "/"))

@Route(r'/reg', name='admin_reg')
class RegHandler(BaseHandler):
    def get(self):
        self.render('reg.html')

    def post(self):
        umobile = self.get_argument('username')
        upwd = self.get_argument('password')
        if util.vmobile(umobile) and upwd:
            if User.select().where(User.umobile == umobile).count() == 0:
                User.create(umobile = umobile, upwd = User.create_password(upwd))
                return self.redirect(self.get_login_url())
            return  self.write("<script>alert('用户名已被注册');history.back();</script>")
        return self.write("<script>alert('用户名为11位手机号且密码不能为空');history.back();</script>")

##########################################################################################################################
@Route(r'/task/(.*)', name='task_handler')
class TaskHandler(BaseHandler):
    def get(self,task_id):
        uq = (models.Task.task_id==task_id)
        ret = models.IPTask.select().join(models.Task).where(uq)
        self.render('ipscantask.html',data = ret)

    def post(self,method):
        assert method in ('create','delete')

#########################################################################################################################
@Route(r'/result/portscan', name='ipscan_handler')
class IpscanHandler(BaseHandler):
    def get(self):
        pagesize = 1000
        page = int(self.get_argument("page", 1))
        keytype = self.get_argument("keytype", "port")
        keyword = self.get_argument("keyword", None)
        uq = (models.PortResult.id > 0)
        if keyword:
            if keytype=='ip':
                uq = uq&(models.IPResult.ip%("*%s*"%keyword))
            elif keytype=='port':
                uq = uq&(models.PortResult.port%("*%s*"%keyword))
            elif keytype=='state':
                uq = uq&(models.PortResult.status_code%("*%s*"%keyword))
            elif keytype=='banner':
                uq = uq&(models.PortResult.banner%("*%s*"%keyword))
            else:
                uq = uq&(models.PortResult.title%("*%s*"%keyword))
                uq = uq&(models.PortResult.headers%("*%s*"%keyword))
                uq = uq&(models.PortResult.content%("*%s*"%keyword))

        res = models.PortTask.select().join(
             models.IPResult).where(
             models.IPResult.ip==task_id).get()

        total = res.count()
        data = res.paginate(page, pagesize)
        self.render('ipscan.html', data = data, total = total, page = page, pagesize = pagesize)